import pygame
# Initialize pygame
pygame.init()
= pygame.display.set_mode((800, 600)) # Set the screen
screen 'My Pygame Window') # Set the window title
pygame.display.set_caption(
= True
running while running:
# Check for events
for event in pygame.event.get():
if event.type == pygame.QUIT:
= False
running
# Update game state
# Render graphics
# Update the display
pygame.display.flip()
pygame.quit()
02-19-24 (Monday)
Lord, you reveal your glory in every thing you made
Let us today engage with this creation so that we may participate in your beauty and wisdom
May the technology we use or even develop point us toward that,
Instead of dragging us towards our own vicious desires and illusions of freedom
Help us, and our society, to know your ways and be still, for yours is the glory
And our hearts are restless till they find rest in You.
Amen.
1 PyGame basics
What do I have to know?
1.1 Main game loop
- Import
pygame
- Initialize
- Set up the display screen
- Create the main game loop, with usually the steps:
- Catch events
- Update game states
- Draw everything
- Quit the game in the event “QUIT”
1.2 Drawing/Rendering
import pygame
# Initialize pygame
pygame.init()
= pygame.display.set_mode((800, 600)) # Set the screen
screen 'My Pygame Window') # Set the window title
pygame.display.set_caption(
= True
running while running:
# Check for events
for event in pygame.event.get():
if event.type == pygame.QUIT:
= False
running
# Fill the screen with white
screen.fill(WHITE)
# Draw a red circle in the center of the screen
400, 300), 50)
pygame.draw.circle(screen, RED, (
# Update the display
pygame.display.flip()
pygame.quit()
- Example 2: rendering sprites (get the image here)
- Load the sprite before the game loop
- Use “blit” to draw the sprite
import pygame
# Initialize pygame
pygame.init()
# Set constants
= 800, 600
WIDTH, HEIGHT = (255, 255, 255)
WHITE
= pygame.display.set_mode((800, 600)) # Set the screen
screen 'My Pygame Window') # Set the window title
pygame.display.set_caption(
# Load the smiley face image
= pygame.image.load("smiley.png")
smiley_image = smiley_image.get_rect()
smiley_rect = (WIDTH // 2, HEIGHT // 2)
smiley_rect.center
= True
running while running:
# Check for events
for event in pygame.event.get():
if event.type == pygame.QUIT:
= False
running
# Draw
screen.fill(WHITE)
screen.blit(smiley_image, smiley_rect)
# Update the display
pygame.display.flip()
pygame.quit()
1.3 Animating
- Add parameters for center, radius and speed to make our smiley rotate
- Update position according to each run of the game loop
- Use
clock.tick()
to set a constant FPS rate at the game
import pygame
import math
# Initialize pygame
pygame.init()
# Set constants
= 800, 600
WIDTH, HEIGHT = (255, 255, 255)
WHITE
= pygame.display.set_mode((800, 600)) # Set the screen
screen 'My Pygame Window') # Set the window title
pygame.display.set_caption(
# Load the smiley face image
= pygame.image.load("smiley.png")
smiley_image = smiley_image.get_rect()
smiley_rect
# Animation parameters
= 200
radius = 0
angle = 0.02 # Controls the speed of the animation
speed
= pygame.time.Clock() # start the clock
clock = True
running while running:
# Check for events
for event in pygame.event.get():
if event.type == pygame.QUIT:
= False
running
# Update state
### Update position
= WIDTH // 2 + int(math.cos(angle) * radius)
x = HEIGHT // 2 + int(math.sin(angle) * radius)
y = (x, y)
smiley_rect.center ### Update angle for next frame
+= speed
angle
# Draw
screen.fill(WHITE)
screen.blit(smiley_image, smiley_rect)
# Update the display
pygame.display.flip() 60)
clock.tick(
pygame.quit()
1.4 Catching events
- You can catch more events such as mouse clicks or keyboard presses. For a list of event types, see here.
- Let’s add the event of right and left arrow pressing to change the direction of the smiley
import pygame
import math
# Initialize pygame
pygame.init()
# Set constants
= 800, 600
WIDTH, HEIGHT = (255, 255, 255)
WHITE
= pygame.display.set_mode((800, 600)) # Set the screen
screen 'My Pygame Window') # Set the window title
pygame.display.set_caption(
# Load the smiley face image
= pygame.image.load("smiley.png")
smiley_image = smiley_image.get_rect()
smiley_rect
# Animation parameters
= 200
radius = 0
angle = 0.02 # Controls the speed of the animation
speed
= pygame.time.Clock() # start the clock
clock = True
running while running:
# Check for events
for event in pygame.event.get():
if event.type == pygame.QUIT:
= False
running elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
= 0.02
speed elif event.key == pygame.K_LEFT:
= -0.02
speed
# Update state
### Update position
= WIDTH // 2 + int(math.cos(angle) * radius)
x = HEIGHT // 2 + int(math.sin(angle) * radius)
y = (x, y)
smiley_rect.center ### Update angle for next frame
+= speed
angle
# Draw
screen.fill(WHITE)
screen.blit(smiley_image, smiley_rect)
# Update the display
pygame.display.flip() 60)
clock.tick(
pygame.quit()
1.5 Creating some classes
- Let’s create a class “Player” to represent our main character: John Calvin.
- Calvin
= 0.75 # setting a gravity constant
GRAVITY
# Player class
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("calvin_char.png")
self.rect = self.image.get_rect()
self.rect.center = (WIDTH // 2, HEIGHT // 2)
self.velocity = pygame.math.Vector2(0, 0) # setting a vector velocity
def update(self):
# Apply gravity
self.velocity.y += GRAVITY
self.rect.y += self.velocity.y
# Check collision with floor
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
self.velocity.y = 0
def jump(self):
self.velocity.y = -12 # Jump strength
- Now, we create the player and render in the screen.
- You can use a sprite group to update and draw everything together! Just implement the function “update()” in all of them!
import pygame
# Initialize Pygame
pygame.init()
# Constants
= 800, 600
WIDTH, HEIGHT = 60
FPS = (0, 0, 0)
BLACK = (255, 255, 255)
WHITE = 0.75
GRAVITY
# Set up the game window
= pygame.display.set_mode((WIDTH, HEIGHT))
screen "Super Calvin Jump")
pygame.display.set_caption(
# Player class
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("calvin_char.png")
self.rect = self.image.get_rect()
self.rect.center = (WIDTH // 2, HEIGHT // 2)
self.velocity = pygame.math.Vector2(0, 0) # setting a vector velocity
def update(self):
# Apply gravity
self.velocity.y += GRAVITY
self.rect.y += self.velocity.y
# Check collision with floor
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
self.velocity.y = 0
def jump(self):
self.velocity.y = -12 # Jump strength
= pygame.time.Clock()
clock = Player() # create Calvin!
player = pygame.sprite.Group(player) # add Calvin to the sprite group
all_sprites
# game loop
= True
running while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
= False
running elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.jump()
# Update everything
all_sprites.update()
# Render everything
screen.fill(WHITE)
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
- Let’s make it move left and right.
- You can also check for events at the very time of the update. This is another way to implement some kind of logic.
= 5
MOVE_SPEED
# Player class
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("calvin_char.png")
self.rect = self.image.get_rect()
self.rect.center = (WIDTH // 2, HEIGHT // 2)
self.velocity = pygame.math.Vector2(0, 0) # setting a vector velocity
def update(self):
# Apply gravity
self.velocity.y += GRAVITY
self.rect.y += self.velocity.y
# Check collision with floor
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
self.velocity.y = 0
# Handle horizontal movement
= pygame.key.get_pressed()
keys if keys[pygame.K_LEFT]:
self.velocity.x = -MOVE_SPEED
elif keys[pygame.K_RIGHT]:
self.velocity.x = MOVE_SPEED
else:
self.velocity.x = 0
self.rect.x += self.velocity.x
def jump(self):
self.velocity.y = -12 # Jump strength
1.6 Collision detection
- Let’s add some blocks to our scene.
- We now need to check if Calvin is colliding with them!
class Block(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
super().__init__()
self.image = pygame.Surface((width, height))
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.topleft = (x, y)
- We can add them to a new group of blocks.
# Create blocks
= pygame.sprite.Group()
blocks 200, 400, 100, 20))
blocks.add(Block(400, 300, 100, 20))
blocks.add(Block(600, 200, 100, 20))
blocks.add(Block(
# Create player
= Player()
player = pygame.sprite.Group(player) all_sprites
- And now, in the update function of Player, we check for collisions. We will use the function
pygame.sprite.spritecollide
.- We add the blocks group to the Player update function.
def update(self, blocks):
# update position
self.rect.x += self.velocity.x
self.rect.y += self.velocity.y
# update velocities
self.velocity.y += GRAVITY
= pygame.key.get_pressed()
keys if keys[pygame.K_LEFT]:
self.velocity.x = -MOVE_SPEED
elif keys[pygame.K_RIGHT]:
self.velocity.x = MOVE_SPEED
else:
self.velocity.x = 0
# Check collision with walls
= pygame.sprite.spritecollide(self, blocks, False)
collisions for block in collisions:
= self.rect.clip(block.rect)
clip_rect if clip_rect.width > clip_rect.height: # up or down
if self.rect.bottom > block.rect.top and self.rect.bottom < block.rect.bottom:
self.rect.bottom = block.rect.top
self.velocity.y = 0
elif self.rect.top < block.rect.bottom:
self.rect.top = block.rect.bottom
self.velocity.y = 0
else: # right or left
if self.rect.right > block.rect.left and self.rect.right < block.rect.right:
self.rect.right = block.rect.left
self.velocity.x = 0
elif self.rect.left < block.rect.right:
self.rect.left = block.rect.right
self.velocity.x = 0
# Check collision with floor
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
self.velocity.y = 0
- In this case, we will detect collision only in terms of rectangles. Later, you may need to implement a collision mask. See here.
1.7 Sound
- Let’s add a jump sound. Out of the main loop, load the sound:
= pygame.mixer.Sound('jump.mp3') jump_sound
- Now make it play when Calvin jumps!
def jump(self):
self.velocity.y = -12 # Jump strength
jump_sound.play()
1.8 Multiple scenes
- There are many ways to create multiple scenes, but a simple one is just create a function for each scene. For example:
def main_menu():
= pygame.image.load("supercalvin.png")
bg = pygame.transform.scale(bg, (800, 600))
bg # game loop
= True
running while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
= False
running
pygame.quit()elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
= False
running
# Render everything
0, 0))
screen.blit(bg, (
pygame.display.flip()
clock.tick(FPS)
def first_level():
# background
= pygame.image.load("geneva.jpg")
bg = pygame.transform.scale(bg, (800, 600))
bg
# game loop
= True
running while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
= False
running elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.jump()
# Update everything
player.update(blocks)
blocks.update()
# Render everything
0, 0))
screen.blit(bg, (
player_g.draw(screen)
blocks.draw(screen)
pygame.display.flip()
clock.tick(FPS)
main_menu()
first_level() pygame.quit()